//
// Created by qiangqiangj on 2019/10/30.
//

#include "url.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>

#define BUFFSIZE 4096
#define TEXT_BUFFSIZE 1024

char *post_json(const char *urls, char *json) {
    struct URL *url = url_parse(urls);
    char *host = url->host;
    int port = url->port;
    char *path = url->path;
    char request[BUFFSIZE], requestHeader[BUFFSIZE], responseHeader[BUFFSIZE], text[BUFFSIZE];
    int socketid, connectid, res, recvid, flag = 1;
    struct hostent *purl = NULL;
    struct sockaddr_in sockinfo;

    socketid = socket(AF_INET, SOCK_STREAM, 0);
    if (socketid == -1) {
        printf("创建socket连接失败\n");
        exit(1);
    }

    // 返回值 ：成功返回hostent结构指针，失败则返回NULL指针
    purl = gethostbyname(host);

    // 设置连接信息结构
    memset(&sockinfo, 0, sizeof(struct sockaddr_in));
    sockinfo.sin_family = AF_INET;
    sockinfo.sin_addr.s_addr = *((unsigned long *) purl->h_addr_list[0]);
    sockinfo.sin_port = htons(port);

    // 构造http请求
    memset(request, 0, BUFFSIZE);
    strcat(request, "POST /");
    strcat(request, path);
    strcat(request, " HTTP/1.1\r\n");
    // 以上为http请求行信息
    strcat(request, "HOST: ");
    strcat(request, host);
    strcat(request, "\r\n");
    strcat(request, "User-Agent: http-ci\r\n");
    strcat(request, "Content-Type: application/json;charset=UTF-8\r\n");
    strcat(request, "Connection: close\r\n");
    sprintf(request,"%s%s%lu\r\n\r\n%s",request,"Content-Length: ",strlen(json),json);

    printf("\nrequest: %s", request);

    // 连接到远端服务器
    connectid = connect(socketid, (struct sockaddr *) &sockinfo, sizeof(sockinfo));
    if (connectid == -1) {
        printf("连接远端服务器失败\n");
        exit(1);
    }

    // 向服务器发送POST请求
    res = write(socketid, request, strlen(request));

    if (res == -1) {
        printf("向服务器发送GET请求失败\n");
        exit(1);
    }

    // 接受服务器的响应
    while (flag) {
        memset(text, 0, TEXT_BUFFSIZE);
        int bufflen = recv(socketid, text, TEXT_BUFFSIZE, 0);
        if (bufflen < 0) {
            printf("接收数据流出错\n");
            fclose(stdout);
            close(socketid);
            exit(1);
        }

        if (bufflen > 0) {
            printf("%s", text);
        } else {
            flag = 0;
        }
    }
    fclose(stdout);
    close(socketid);
}

char *post_chunk(const char *urls) {
    struct URL *url = url_parse(urls);
    char *host = url->host;
    int port = url->port;
    char *path = url->path;
    char request[BUFFSIZE], text[BUFFSIZE];
    int socketid, connectid, res, flag = 1;
    struct hostent *purl = NULL;
    struct sockaddr_in sockinfo;

    socketid = socket(AF_INET, SOCK_STREAM, 0);
    if (socketid == -1) {
        printf("创建socket连接失败\n");
        exit(1);
    }

    // 返回值 ：成功返回hostent结构指针，失败则返回NULL指针
    purl = gethostbyname(host);

    // 设置连接信息结构
    memset(&sockinfo, 0, sizeof(struct sockaddr_in));
    sockinfo.sin_family = AF_INET;
    sockinfo.sin_addr.s_addr = *((unsigned long *) purl->h_addr_list[0]);
    sockinfo.sin_port = htons(port);

    // 构造http请求
    memset(request, 0, BUFFSIZE);
    strcat(request, "POST /");
    strcat(request, path);
    strcat(request, " HTTP/1.1\r\n");
    // 以上为http请求行信息
    strcat(request, "HOST: ");
    strcat(request, host);
    strcat(request, "\r\n");
    strcat(request, "User-Agent: http-ci\r\n");
    strcat(request, "Transfer-Encoding: chunked\r\n");
    strcat(request, "Connection: close\r\n");
    strcat(request, "\r\n");

    printf("request: \r\n%s\r\n", request);

    // 连接到远端服务器
    connectid = connect(socketid, (struct sockaddr *) &sockinfo, sizeof(sockinfo));
    if (connectid == -1) {
        printf("连接远端服务器失败\n");
        exit(1);
    }
    printf("-> 连接到远端服务器成功\n");

    // 向服务器发送POST请求头
    res = write(socketid, request, strlen(request));
    int writeRet = 0;

    int content_len = 0;
    char *audio_data;
    char *filename = "/home/qiangqiangj/CLionProjects/http-cli/16k.pcm";
    FILE *fp = fopen(filename, "r");

    size_t cnt = 0;
    for (;;) {
        char buf[BUFFSIZE];
        char len[10];
        unsigned int rn = fread(buf, sizeof(char), BUFFSIZE, fp);
        sprintf(len, "%x\r\n", rn);
        write(socketid, len, strlen(len));
        write(socketid, buf, rn);
        write(socketid, "\r\n", 2);
//        printf("%s---%lu\r\n", len,strlen(len));
//        sprintf(buf, "%d\r\n", rn);
//        printf("%s", buf);
        cnt += rn;
        if (rn < BUFFSIZE) {
            break;
        }
    }

    // 发送chunk结束块
    writeRet = write(socketid, "0\r\n\r\n", 5);

    // 接受服务器的响应
    while (flag) {
        memset(text, 0, TEXT_BUFFSIZE);
        int bufflen = recv(socketid, text, TEXT_BUFFSIZE, 0);
        if (bufflen < 0) {
            printf("接收数据流出错\n");
            fclose(stdout);
            close(socketid);
            exit(1);
        }

        if (bufflen > 0) {
            printf("%s", text);
        } else {
            flag = 0;
        }
    }
    fclose(stdout);
    close(socketid);
}

// 从fp读取文件内容，长度保存在content_len
char *read_file_data(FILE *fp, int *content_len) {
    fseek(fp, 0, SEEK_END);
    int len = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    *content_len = len;
    char *data = (char *) malloc(len);
    if (data == NULL) {
        fprintf(stderr, "malloc size %d failed", len);
        exit(11);
    }
    fread(data, 1, len, fp);
    return data;
}

char *post_audio(const char *urls) {
    struct URL *url = url_parse(urls);
    char *host = url->host;
    int port = url->port;
    char *path = url->path;
    char request[BUFFSIZE], requestHeader[BUFFSIZE], responseHeader[BUFFSIZE], text[BUFFSIZE];
    int socketid, connectid, res, recvid, flag = 1;
    struct hostent *purl = NULL;
    struct sockaddr_in sockinfo;

    socketid = socket(AF_INET, SOCK_STREAM, 0);
    if (socketid == -1) {
        printf("创建socket连接失败\n");
        exit(1);
    }

    // 返回值 ：成功返回hostent结构指针，失败则返回NULL指针
    purl = gethostbyname(host);

    // 设置连接信息结构
    memset(&sockinfo, 0, sizeof(struct sockaddr_in));
    sockinfo.sin_family = AF_INET;
    sockinfo.sin_addr.s_addr = *((unsigned long *) purl->h_addr_list[0]);
    sockinfo.sin_port = htons(port);

    // 构造http请求
    memset(request, 0, BUFFSIZE);
    strcat(request, "POST /");
    strcat(request, path);
    strcat(request, " HTTP/1.1\r\n");
    // 以上为http请求行信息
    strcat(request, "HOST: ");
    strcat(request, host);
    strcat(request, "\r\n");
    strcat(request, "User-Agent: http-ci\r\n");
    strcat(request, "Content-Type: application/json;charset=UTF-8\r\n");
    strcat(request, "Connection: close\r\n");

    char *filename = "/home/qiangqiangj/CLionProjects/http-cli/16k.pcm";
    int content_len = 0;
    char *audio_data;

    FILE *fp = fopen(filename, "r");
    audio_data = read_file_data(fp, &content_len);


    sprintf(request, "%s%s%d\r\n\r\n", request, "Content-Length: ", content_len);

    printf("\nrequest: %s", request);

    // 连接到远端服务器
    connectid = connect(socketid, (struct sockaddr *) &sockinfo, sizeof(sockinfo));
    if (connectid == -1) {
        printf("连接远端服务器失败\n");
        exit(1);
    }

    // 向服务器发送POST请求
    // 分批发送数据 避免修改request
    res = write(socketid, request, strlen(request));
    res = write(socketid, audio_data, content_len);

    if (res == -1) {
        printf("向服务器发送GET请求失败\n");
        exit(1);
    }

    // 接受服务器的响应
    while (flag) {
        memset(text, 0, TEXT_BUFFSIZE);
        int bufflen = recv(socketid, text, TEXT_BUFFSIZE, 0);
        if (bufflen < 0) {
            printf("接收数据流出错\n");
            fclose(stdout);
            close(socketid);
            exit(1);
        }

        if (bufflen > 0) {
            printf("%s", text);
        } else {
            flag = 0;
        }
    }
    fclose(stdout);
    close(socketid);
}